package org.codehaus.activemq.store.bdb;

import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.Transaction;
import java.io.File;
import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BDbHelper
{
  private static final Log log = LogFactory.getLog(BDbHelper.class);
  private static ThreadLocal threadLocalTxn = new ThreadLocal();

  public static Environment createEnvironment(File dir) throws DatabaseException {
    EnvironmentConfig envConfig = new EnvironmentConfig();
    envConfig.setAllowCreate(true);
    envConfig.setTransactional(true);
    return new Environment(dir, envConfig);
  }

  public static DatabaseConfig createDatabaseConfig() {
    DatabaseConfig config = new DatabaseConfig();
    config.setTransactional(true);
    config.setAllowCreate(true);
    return config;
  }

  public static Transaction getTransaction()
  {
    LinkedList list = (LinkedList)threadLocalTxn.get();
    if ((list != null) && (!list.isEmpty())) {
      return (Transaction)list.getFirst();
    }
    return null;
  }

  public static Transaction popTransaction()
  {
    LinkedList list = (LinkedList)threadLocalTxn.get();
    if ((list == null) || (list.isEmpty())) {
      log.warn("Attempt to pop transaction when no transaction in progress");
      return null;
    }

    return (Transaction)list.removeFirst();
  }

  public static void pushTransaction(Transaction transaction)
  {
    LinkedList list = (LinkedList)threadLocalTxn.get();
    if (list == null) {
      list = new LinkedList();
      threadLocalTxn.set(list);
    }
    list.addLast(transaction);
  }

  public static int getTransactionCount() {
    LinkedList list = (LinkedList)threadLocalTxn.get();
    if (list != null) {
      return list.size();
    }
    return 0;
  }

  public static byte[] asBytes(long v) {
    byte[] data = new byte[8];
    data[0] = (byte)(int)(v >>> 56);
    data[1] = (byte)(int)(v >>> 48);
    data[2] = (byte)(int)(v >>> 40);
    data[3] = (byte)(int)(v >>> 32);
    data[4] = (byte)(int)(v >>> 24);
    data[5] = (byte)(int)(v >>> 16);
    data[6] = (byte)(int)(v >>> 8);
    data[7] = (byte)(int)(v >>> 0);
    return data;
  }

  public static byte[] asBytes(Long key) {
    long v = key.longValue();
    return asBytes(v);
  }

  public static long longFromBytes(byte[] data) {
    return (data[0] << 56) + ((data[1] & 0xFF) << 48) + ((data[2] & 0xFF) << 40) + ((data[3] & 0xFF) << 32) + ((data[4] & 0xFF) << 24) + ((data[5] & 0xFF) << 16) + ((data[6] & 0xFF) << 8) + ((data[7] & 0xFF) << 0);
  }
}